﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace PIM_ATE
{
    public class ClsDataConfigBase
    {
        protected ProcodeINFO m_cProceodeINFO;
        protected string m_sProcodeID;
        protected string m_sProcode;
        protected string m_sVerConfig;
        protected string m_sVerSpec;

        protected string m_sConnect;
        protected string TABLE_NAME = "tb_PIMConfig";
        protected string CONFIG_TYPE = "ANTENNA";
        protected string CONDITION_SQL = " and [Type] = 'ANTENNA';";

        protected Hashtable m_nodePairs = new Hashtable();

        public ClsDataConfigBase(string alias)
        {
            m_sConnect = alias;
        }

        #region DataBase

        public static bool createConfigDataTable()
        {
            //CREATE TABLE "tb_PIMConfig" (
            //    "ID" INT IDENTITY(1,1) NOT NULL,
            //    "Type" NVARCHAR(50) NOT NULL,
            //    "ProCode" NVARCHAR(100) NOT NULL,
            //    "SpecVer" NVARCHAR(50) NOT NULL,
            //    "ConfigVer" NVARCHAR(50) NOT NULL,
            //    "EffTime" DATETIME NULL DEFAULT NULL,
            //    "Effective" NVARCHAR(10) NOT NULL,
            //    "Remark" NVARCHAR(100) NULL DEFAULT NULL,
            //    "Config" XML NOT NULL,
            //    "Setting" XML NULL DEFAULT NULL
            //)
            //;
            return false;
        }

        public static List<string> getDBColNames()
        {
            List<string> names = new List<string>();
            names.Add("Type");
            names.Add("ProCode");
            names.Add("SpecVer");
            names.Add("ConfigVer");
            names.Add("EffTime");
            names.Add("Effective");
            names.Add("Remark");
            names.Add("Config");
            names.Add("Setting");
            return names;
        }

        #endregion

        public void construct(string sProcodeID)
        {//设置产品ID
            m_sProcodeID = sProcodeID;
        }

        public bool construct(string sProCode, string sProVer)
        {//通过产品代码查找产品ID
            bool ret = false;
            //constructByProcode(sProCode);
            float fVer = 0;
            try { fVer = Convert.ToSingle(sProVer); }
            catch { System.Windows.Forms.MessageBox.Show("construct: 配置的版本格式化错误!"); return false; }

            if (m_nodePairs.ContainsKey(fVer))
            {
                m_cProceodeINFO = (m_nodePairs[fVer] as ProcodeINFO);
                m_sProcodeID = m_cProceodeINFO.sID;

                m_sProcode = m_cProceodeINFO.sProCode;
                m_sVerConfig = m_cProceodeINFO.sConfigVer;
                m_sVerSpec = m_cProceodeINFO.sSpecVer;
                ret = true;
            }
            return ret;
        }

        public string[] constructByProcode(string sProcode)
        {
            List<string> lstVer = new List<string>();
            m_nodePairs.Clear();
            string sSql = string.Format("select [ID],[SpecVer],[ConfigVer],[EffTime],[Effective],[Remark] from {0} where [Procode] = '{1}'",
                                     TABLE_NAME, sProcode);
            sSql += " and [Type] = '" + CONFIG_TYPE + "'";
            sSql += " order by [ConfigVer];";
            DataTable dtVer = MicroDBHelper.ExecuteDataTable(sSql, null, m_sConnect);
            for (int j = 0; j < dtVer.Rows.Count; j++)
            {
                string sVer = dtVer.Rows[j][2].ToString();
                ProcodeINFO info = new ProcodeINFO()
                {
                    sProCode = sProcode.ToUpper(),
                    sID = dtVer.Rows[j][0].ToString(),
                    sSpecVer = dtVer.Rows[j][1].ToString(),
                    sConfigVer = dtVer.Rows[j][2].ToString(),
                    sEffTime = dtVer.Rows[j][3].ToString(),
                    bEffective = PIMFunction.getBoolean(dtVer.Rows[j][4].ToString()),
                    sRemark = dtVer.Rows[j][5].ToString()
                };

                try
                {
                    float fVer = Convert.ToSingle(sVer);
                    m_nodePairs.Add(fVer, info);
                }
                catch { System.Windows.Forms.MessageBox.Show("constructByProcode: 配置的版本格式化错误!"); return null; }
                lstVer.Add(sVer);
            }

            return lstVer.ToArray();
        }

        public List<ProcodeNode> getNodeList()
        {//构建配置总表
            //ListProcdeNodes.Clear();
            List<ProcodeNode> m_lstNodes = new List<ProcodeNode>();

            string sSql = string.Format("select distinct [ProCode] from {0} where [Type] = '{1}'", TABLE_NAME, CONFIG_TYPE);
            DataTable dtProcode = MicroDBHelper.ExecuteDataTable(sSql, null, m_sConnect);
            for (int i = 0; i < dtProcode.Rows.Count; i++)
            {
                ProcodeNode node = new ProcodeNode();
                node.Procode = dtProcode.Rows[i][0].ToString().ToUpper();
                node.ListProcodeID = new List<string>();
                node.ListProcodeVersion = new List<string>();
                node.ListProcodeSpecVersion = new List<string>();
                node.ListProcodeINFO = new List<ProcodeINFO>();

                sSql = string.Format("select [ID],[SpecVer],[ConfigVer],[EffTime],[Effective],[Remark] from {0} where [Procode] = '{1}'",
                                     TABLE_NAME, node.Procode);
                sSql += CONDITION_SQL;
                DataTable dtVer = MicroDBHelper.ExecuteDataTable(sSql, null, m_sConnect);
                for (int j = 0; j < dtVer.Rows.Count; j++)
                {
                    node.ListProcodeID.Add(dtVer.Rows[j][0].ToString());            
                    node.ListProcodeSpecVersion.Add(dtVer.Rows[j][1].ToString());
                    node.ListProcodeVersion.Add(dtVer.Rows[j][2].ToString());

                    ProcodeINFO info = new ProcodeINFO()
                    {
                        sProCode = node.Procode,
                        sID = dtVer.Rows[j][0].ToString(),
                        sSpecVer = dtVer.Rows[j][1].ToString(),
                        sConfigVer = dtVer.Rows[j][2].ToString(),
                        sEffTime = dtVer.Rows[j][3].ToString(),
                        bEffective = PIMFunction.getBoolean(dtVer.Rows[j][4].ToString()),
                        sRemark = dtVer.Rows[j][5].ToString()
                    };
                    node.ListProcodeINFO.Add(info);
                }
                m_lstNodes.Add(node);
            }

            return m_lstNodes;
        }

        public string[] getProcodeList()
        {//构建配置总表
            List<string> lstCode = new List<string>();
            string sSql = string.Format("select distinct [ProCode] from {0} where [Type] = '{1}'", TABLE_NAME, CONFIG_TYPE);
            DataTable dtProcode = MicroDBHelper.ExecuteDataTable(sSql, null, m_sConnect);
            for (int i = 0; i < dtProcode.Rows.Count; i++)
            {
                lstCode.Add(dtProcode.Rows[i][0].ToString().ToUpper());
            }

            return lstCode.ToArray();
        }

        public bool updateXml(bool bEffective, string xmlConfig = "")
        {
            if (m_sProcodeID == null || m_sProcodeID == "")
            {//错误
                //error_info = "当前实例未构造sProCode";
                return false;
            }

            int ret = -1;
            try
            {
                using (var tran = MicroDBHelper.UseTransaction(IsolationLevel.RepeatableRead, m_sConnect))
                {//开始上传
                    string sCondition = "";
                    string sEffective = bEffective.ToString();
                    List<SqlParameter> lstParam = new List<SqlParameter>();
                    lstParam.Add(new SqlParameter("@id", m_sProcodeID));
                    lstParam.Add(new SqlParameter("@specVer", m_sVerSpec));
                    lstParam.Add(new SqlParameter("@eff", sEffective));
                    DateTime now = DateTime.Parse(PIMFunction.getTime(m_sConnect));
                    lstParam.Add(new SqlParameter("@efftime", now));
                    if (xmlConfig != "")
                    {
                        lstParam.Add(new SqlParameter("@cfg", xmlConfig));
                        sCondition = ", [Config] = @cfg";
                    }

                    string sSql = "update " + TABLE_NAME + " set [Effective] = @eff, [EffTime] = @efftime, [SpecVer] = @specVer" +
                                  sCondition + " where [ID] = @id";
                    ret = MicroDBHelper.ExecuteNonQuery(sSql, lstParam.ToArray(), tran);
                    tran.MarkSuccess();
                }
            }
            catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); }
            return ret > 0;
        }

        public int delete()
        {
            if (m_sProcodeID == null || m_sProcodeID == "")
            {//错误
                //error_info = "当前实例未构造sProCode";
                return -1;
            }
            int ret = -1;
            try
            {
                using (var tran = MicroDBHelper.UseTransaction(IsolationLevel.RepeatableRead, m_sConnect))
                {//开始上传
                    List<SqlParameter> lstParam = new List<SqlParameter>();
                    lstParam.Add(new SqlParameter("@id", m_sProcodeID));

                    string sSql = "delete from " + TABLE_NAME + " where [ID] = @id";
                    ret = MicroDBHelper.ExecuteNonQuery(sSql, lstParam.ToArray(), tran);
                    tran.MarkSuccess();
                }
            }
            catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); }
            return ret;
        }

        protected string downloadXml()
        {
            if (m_sProcodeID == null || m_sProcodeID == "")
            {//错误
                //error_info = "当前实例未构造sProCode";
                return "";
            }

            string sXml = "";
            try
            {
                List<SqlParameter> lstParam = new List<SqlParameter>();
                lstParam.Add(new SqlParameter("@id", m_sProcodeID));

                string sSql = "select [Config] from " + TABLE_NAME + " where [ID] = @id";
                sXml = MicroDBHelper.ExecuteScalar(sSql, lstParam.ToArray(), m_sConnect).ToString();
            }
            catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); }
            return sXml;
        }

        protected bool uploadXml(string sProcode, string sConfigVer, string xmlConfig, ref string error_info, string sSpecVer = "1.0")
        {//上传配置
            ProcodeINFO procodeObj = new ProcodeINFO();
            procodeObj.sSpecVer = sSpecVer;
            procodeObj.sConfigVer = sConfigVer;
            procodeObj.sProCode = sProcode;
            procodeObj.sEffTime = "";
            procodeObj.bEffective = true;
            procodeObj.sRemark = "";

            return uploadXml(procodeObj, xmlConfig, ref error_info);
        }

        protected bool uploadXml(ProcodeINFO procodeNew, string xmlConfig, ref string error_info)
        {//上传配置,无需构造
            try
            {
                string sProcode = procodeNew.sProCode;
                string sConfigVer = procodeNew.sConfigVer;
                string sSqlCheck = string.Format("select count(*) from {0} where [ProCode] = '{1}' and [ConfigVer] = '{2}'",
                                                  TABLE_NAME, sProcode, sConfigVer);
                sSqlCheck += CONDITION_SQL;
                int count = Convert.ToInt32(MicroDBHelper.ExecuteScalar(sSqlCheck, null, m_sConnect));
                if (count > 0)
                {//查询是否已存在
                    System.Windows.Forms.MessageBox.Show("当前版本重复，请重新设置");
                    return false;
                }

                using (var tran = MicroDBHelper.UseTransaction(IsolationLevel.RepeatableRead, m_sConnect))
                {//开始上传
                    string strXml = xmlConfig;
                    string strSpecVer = procodeNew.sSpecVer;
                    DateTime now = DateTime.Parse(PIMFunction.getTime(m_sConnect));
                    string strEffTime = now.ToString("yyyy-MM-dd HH:mm:ss");
                    string strEffective = procodeNew.bEffective.ToString();
                    string sDBColNames = PIMFunction.getColNameString(getDBColNames());

                    string sValues = "";
                    sValues += "'" + CONFIG_TYPE + "',";
                    sValues += "'" + sProcode + "',";
                    sValues += "'" + strSpecVer + "',";
                    sValues += "'" + sConfigVer + "',";
                    sValues += "'" + strEffTime + "',";
                    sValues += "'" + strEffective + "',";
                    sValues += "'',";
                    sValues += "'" + strXml + "',";
                    sValues += "''";
                    string sSqlUpload = String.Format("insert into {0} ({1}) values ({2});",
                                                       TABLE_NAME, sDBColNames, sValues);
                    MicroDBHelper.ExecuteNonQuery(sSqlUpload, null, tran);
                    tran.MarkSuccess();
                }
            }
            catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); return false; }
            return true;
        }

        public virtual DataTable getProCodeTable()
        {
            return null;
        }
    }

    public class ProcodeNode
    {
        public string Procode { get; set; }
        public List<string> ListProcodeSpecVersion { get; set; }
        public List<string> ListProcodeVersion { get; set; }
        public List<string> ListProcodeID { get; set; }
        public List<ProcodeINFO> ListProcodeINFO { get; set; }
    }

    public class ProcodeINFO
    {
        public string sID;
        public string sProCode;
        public string sSpecVer;
        public string sConfigVer;
        public string sEffTime;
        public bool bEffective;
        public string sRemark;
    }
}
